/**
 * 
 */
package edu.towson.cosc.cosc455.bmoran.compiler;

import edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer;

/**
 * @author bmoran4
 *
 */
public class MySyntaxAnalyzer implements SyntaxAnalyzer {

	int pVar=0;
	int bVar=0;
	int iVar=0;
	
	@Override
	public void lolcode() {
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.DOC_BEGIN)){
			System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.DOC_BEGIN + "was expected.");
			System.exit(0);
		}
		
		MyCompiler.parseTree.add(MyCompiler.token);
		MyCompiler.Lexer.getNextToken();
		if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.COMMENT_BEGIN)){
			comment();
		}
		if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_DEFINE_BEGIN)){
			define();
		}
		if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.HEAD_BEGIN)){
			head();
		}
			body();
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.DOC_END)){
			System.err.println("Systax error: " + MyCompiler.token + " when " + LexicalTokens.DOC_BEGIN + " was expected.");
		System.exit(0);
		}

		MyCompiler.parseTree.add(MyCompiler.token);
		
		if(!MyCompiler.Lexer.endCheck()){
			System.err.println("Cannot have text after #KTHXBYE");
			System.exit(0);
		}
}

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#comment()
	 */
	@Override
	public void comment() {
		MyCompiler.parseTree.add(MyCompiler.token);
		
		MyCompiler.Lexer.getNextToken();
		
		if(!MyCompiler.token.startsWith("#")){
			text();
		}
		
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.COMMENT_END)){
			System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.COMMENT_END + " was expected.");
		System.exit(0);
		}
		
		MyCompiler.parseTree.add(MyCompiler.token);
		MyCompiler.Lexer.getNextToken();

	}

	
	
	@Override
	public void head() {
	
	MyCompiler.parseTree.add(MyCompiler.token);
		
		MyCompiler.Lexer.getNextToken();
		
		if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.TITLE_BEGIN)){
			title();
		}
		
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.HEAD_END)){
			System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.HEAD_END + " was expected.");
		System.exit(0);
		}
		
		MyCompiler.parseTree.add("</head>");
		MyCompiler.Lexer.getNextToken();

	}

 public void text(){
	MyCompiler.parseTree.add(MyCompiler.token);
		
		MyCompiler.Lexer.getNextToken();
 }
@Override
 public void title(){
	 MyCompiler.parseTree.add(MyCompiler.token);
	 MyCompiler.Lexer.getNextToken();
	 
	 
	 if(!MyCompiler.token.startsWith("#")){
			text();
		}
		
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.TITLE_END)){
			System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.TITLE_END + " was expected.");
		System.exit(0);
		}
		
		MyCompiler.parseTree.add("</title>");
		MyCompiler.Lexer.getNextToken();

	}
public void body(){
	
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.COMMENT_BEGIN)){
		comment();
		body();
		
	}
	innerText();
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.PARAGRAPH_BEGIN)){
		paragraph();
		body();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.BOLD_BEGIN)){
		bold();
		body();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITALICS_BEGIN)){
		italics();
		body();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.LIST_BEGIN)){
		list();
		body();
	}
}
public void innerParagraph(){
	innerText();
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.BOLD_BEGIN)){
		bold();
		innerParagraph();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITALICS_BEGIN)){
		italics();
		innerParagraph();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.LIST_BEGIN)){
		list();
		innerParagraph();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.NEWLINE)){
		newLine();
		innerParagraph();
	}
	

}
public void innerText(){
	
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_USE_BEGIN)){
		use();
		innerText();
	}
	if(!MyCompiler.token.startsWith("#")){
		text();
		innerText();
		
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.NEWLINE)){
		newLine();
		innerText();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.SOUNDS_BEGIN)){
		audio();
		innerText();
	}
	if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.VIDEO_BEGIN)){
		video();
		innerText();
	}
	

}

public void newLine(){	 
	 MyCompiler.parseTree.add(MyCompiler.token);
	 MyCompiler.Lexer.getNextToken();
	 
		if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.NEWLINE)){
			newLine();
		}
}

@Override
public void video() {
	MyCompiler.parseTree.add(MyCompiler.token);
	
	MyCompiler.Lexer.getNextToken();
	
	if(!MyCompiler.token.startsWith("#")){
		text();
	}
	
	if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.VIDEO_END)){
		System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.VIDEO_END + " was expected.");
	System.exit(0);
	}
	
	MyCompiler.parseTree.add("\"/>");
	MyCompiler.Lexer.getNextToken();
	

}

	
	@Override
	public void paragraph() {
		 
			 MyCompiler.parseTree.add(MyCompiler.token);
			 MyCompiler.Lexer.getNextToken();
			 
			 if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_DEFINE_BEGIN)){
				 define();
				 pVar++;				 
			 }
			 	innerParagraph();
			 	
			if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.PARAGRAPH_END)){
				System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.PARAGRAPH_END + " was expected.");
			System.exit(0);
			}
				
			MyCompiler.parseTree.add("</p>");
			MyCompiler.Lexer.getNextToken();
			
			for(int i= 0; i <pVar;i++)
			{
				MyCompiler.compareTokens.get(0).remove(MyCompiler.compareTokens.get(0).size() - 1);
				MyCompiler.compareTokens.get(1).remove(MyCompiler.compareTokens.get(1).size() - 1);
			}
	}

	

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#bold()
	 */
	@Override
	public void bold() {
		MyCompiler.parseTree.add(MyCompiler.token);
		 MyCompiler.Lexer.getNextToken();
		 
		 if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_DEFINE_BEGIN)){
			 define();
			 bVar++;
		 }
		 	innerText();
		 	
			if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.BOLD_END)){
				System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.BOLD_END + " was expected.");
			System.exit(0);
			}
			
			MyCompiler.parseTree.add("</b>");
			MyCompiler.Lexer.getNextToken();

			for(int i= 0; i <bVar;i++)
			{
				MyCompiler.compareTokens.get(0).remove(MyCompiler.compareTokens.get(0).size() - 1);
				MyCompiler.compareTokens.get(1).remove(MyCompiler.compareTokens.get(1).size() - 1);
			}
			
		}

	

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#italics()
	 */
	@Override
	public void italics() {
		MyCompiler.parseTree.add(MyCompiler.token);
		 MyCompiler.Lexer.getNextToken();
		 
		 if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_DEFINE_BEGIN)){
			 define();
			 iVar++;
		 }
		 	innerText();
		 	
			if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITALICS_END)){
				System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.ITALICS_END + " was expected.");
			System.exit(0);
			}
			
			MyCompiler.parseTree.add("</i>");
			MyCompiler.Lexer.getNextToken();

			
			for(int i= 0; i <iVar;i++)
			{
				MyCompiler.compareTokens.get(0).remove(MyCompiler.compareTokens.get(0).size() - 1);
				MyCompiler.compareTokens.get(1).remove(MyCompiler.compareTokens.get(1).size() - 1);
			}
	}

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#list()
	 */
	@Override
	public void list() {
		MyCompiler.parseTree.add(MyCompiler.token);
		MyCompiler.Lexer.getNextToken();
		
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITEM_BEGIN)){
			System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.ITEM_BEGIN + " was expected.");
			System.exit(0);
		}
		else{
			MyCompiler.parseTree.add(MyCompiler.token);
			MyCompiler.Lexer.getNextToken();
			innerList();
			if(!MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITEM_END)){
				System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.ITEM_END + " was expected.");
				System.exit(0);
		}else{
			MyCompiler.parseTree.add(MyCompiler.token);
			MyCompiler.Lexer.getNextToken();
			 if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITEM_BEGIN)){
				 
				item();
			 }
			 
			 if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.LIST_END)){
					System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.LIST_END + " was expected.");
					System.exit(0);
			 }
				MyCompiler.parseTree.add("</ul>");
				MyCompiler.Lexer.getNextToken();
		}
		
		}

	}
	

	
	public void innerList(){
		
		if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.BOLD_BEGIN)){
			bold();
			innerList();
		}
		if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITALICS_BEGIN)){
			italics();
			innerList();
		}
		if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.LIST_BEGIN)){
			list();
			innerList();
		}
		innerText();
	}

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#item()
	 */
	@Override
	public void item() {
		MyCompiler.parseTree.add(MyCompiler.token);
		MyCompiler.Lexer.getNextToken();
		innerList();
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITEM_END)){
			System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.ITEM_END + " was expected.");
	 }
		MyCompiler.parseTree.add("</li>");
		MyCompiler.Lexer.getNextToken();
		
		if(MyCompiler.token.equalsIgnoreCase(LexicalTokens.ITEM_BEGIN)){
			item();
		
		}
	}

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#audio()
	 */
	@Override
	public void audio() {
		MyCompiler.parseTree.add(MyCompiler.token);
		
		MyCompiler.Lexer.getNextToken();
		
		if(!MyCompiler.token.startsWith("#")){
			text();
		}
		
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.SOUNDS_END)){
			System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.SOUNDS_END + " was expected.");
		System.exit(0);
		}
		
		MyCompiler.parseTree.add("\"></audio>");
		MyCompiler.Lexer.getNextToken();
		

	}

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#video()
	 */

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#define()
	 */
	@Override
	public void define() {
		MyCompiler.parseTree.add(MyCompiler.token);
		MyCompiler.Lexer.getNextToken();
		 
		 if(MyCompiler.token.startsWith("#")){
			 System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when a variable name was expected.");
			 System.exit(0);
		}
		 	while (MyCompiler.token.endsWith(" ")){
		 		MyCompiler.token = MyCompiler.token.substring(0, MyCompiler.token.length()-1);
		 	}
		
		defineVariable();
		 //make sure variable is only one word
		 if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_DEFINE_MIDDLE)){
				System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.VARIABLE_DEFINE_MIDDLE + " was expected.");
				System.exit(0);
		 }
		 MyCompiler.parseTree.add(MyCompiler.token);
			MyCompiler.Lexer.getNextToken();
			 
		 if(!MyCompiler.token.startsWith("#")){
				variableDefined();
			}
		 
		 if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_DEFINE_END)){
				System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.VARIABLE_DEFINE_END + " was expected.");
				System.exit(0);
		 }
		 MyCompiler.parseTree.add(MyCompiler.token);
			MyCompiler.Lexer.getNextToken();
		if (MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_DEFINE_BEGIN)){
		 define();
		}
			

	}

	/* (non-Javadoc)
	 * @see edu.towson.cosc.cosc455.interfaces.SyntaxAnalyzer#use()
	 */
	@Override
	public void use() {
		MyCompiler.parseTree.add(MyCompiler.token);
		 MyCompiler.Lexer.getNextToken();
		 
		 if(MyCompiler.token.startsWith("#")){
			 System.err.println("SYNTAX ERROR: You need stuff here");
				System.exit(0);
		 }
		 	while (MyCompiler.token.endsWith(" ")){
		 		MyCompiler.token = MyCompiler.token.substring(0, MyCompiler.token.length()-1);
		 	}
		 	
		 String definedVariable = "";
		 
		 for(int i = MyCompiler.compareTokens.get(0).size() - 1; i >=0; i--)
		 {
			 if(MyCompiler.compareTokens.get(0).get(i).equals(MyCompiler.token))
			 {
				 definedVariable = MyCompiler.compareTokens.get(1).get(i);
				 break;
			 }
		 }
		 
		 if(definedVariable.isEmpty())
		 {
			 System.err.println("Static Semantic Error.. " + MyCompiler.token + " is not a defined variable.");
			 System.exit(0);
		 }
		 
		 MyCompiler.parseTree.add(definedVariable);
		 MyCompiler.Lexer.getNextToken();
		 	
		if (!MyCompiler.token.equalsIgnoreCase(LexicalTokens.VARIABLE_USE_END)){
				System.err.println("SYNTAX ERROR: " + MyCompiler.token + " when " + LexicalTokens.VARIABLE_USE_END + " was expected.");
			System.exit(0);
		}
			
			MyCompiler.parseTree.add(MyCompiler.token);
			MyCompiler.Lexer.getNextToken();

	}
	
	public void defineVariable()
	{
		MyCompiler.compareTokens.get(0).add(MyCompiler.token);
		MyCompiler.Lexer.getNextToken();
	}
	
	public void variableDefined()
	{
		MyCompiler.compareTokens.get(1).add(MyCompiler.token);
		MyCompiler.Lexer.getNextToken();
	}

}
